﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace NetFrameworkExtensions.DataLayer.EF4
{

  public abstract class AuditableData<TIdentified, TIdentifier, TUserIdentifier> :
    DateTimeAuditableData<TIdentified, TIdentifier>,
    IUserAuditableData<TUserIdentifier>
    where TIdentified : AuditableData<TIdentified, TIdentifier, TUserIdentifier>
    where TIdentifier : IEquatable<TIdentifier>
    where TUserIdentifier : struct, IEquatable<TUserIdentifier>
  {
    public virtual TUserIdentifier? CreatedById { get; set; }

    public virtual TUserIdentifier? ModifiedById { get; set; }

    public virtual TUserIdentifier? DeletedById { get; set; }

    [NotMapped]
    object IUserAuditableData.CreatedById
    {
      get
      {
        return CreatedById;
      }
      set
      {
        CreatedById = (TUserIdentifier?)value;
      }
    }

    [NotMapped]
    object IUserAuditableData.ModifiedById
    {
      get
      {
        return ModifiedById;
      }
      set
      {
        ModifiedById = (TUserIdentifier?)value;
      }
    }

    [NotMapped]
    object IUserAuditableData.DeletedById
    {
      get
      {
        return DeletedById;
      }
      set
      {
        DeletedById = (TUserIdentifier?)value;
      }
    }
  }

  public abstract class ReferenceAuditableData<TIdentified, TIdentifier, TUserIdentifier> :
    DateTimeAuditableData<TIdentified, TIdentifier>,
    IReferenceUserAuditableData<TUserIdentifier>
    where TIdentified : ReferenceAuditableData<TIdentified, TIdentifier, TUserIdentifier>
    where TIdentifier : IEquatable<TIdentifier>
    where TUserIdentifier : class, IEquatable<TUserIdentifier>
  {
    public virtual TUserIdentifier CreatedById { get; set; }

    public virtual TUserIdentifier ModifiedById { get; set; }

    public virtual TUserIdentifier DeletedById { get; set; }

    [NotMapped]
    object IUserAuditableData.CreatedById
    {
      get
      {
        return CreatedById;
      }
      set
      {
        CreatedById = (TUserIdentifier)value;
      }
    }

    [NotMapped]
    object IUserAuditableData.ModifiedById
    {
      get
      {
        return ModifiedById;
      }
      set
      {
        ModifiedById = (TUserIdentifier)value;
      }
    }

    [NotMapped]
    object IUserAuditableData.DeletedById
    {
      get
      {
        return DeletedById;
      }
      set
      {
        DeletedById = (TUserIdentifier)value;
      }
    }
  }

  public abstract class IdentityAuditableData<TIdentified, TIdentifier, TUserIdentifier> :
    DateTimeAuditableData<TIdentified, TIdentifier>,
    IUserAuditableData<TUserIdentifier>
    where TIdentified : IdentityAuditableData<TIdentified, TIdentifier, TUserIdentifier>
    where TIdentifier : IEquatable<TIdentifier>
    where TUserIdentifier : struct, IEquatable<TUserIdentifier>
  {
    public virtual TUserIdentifier? CreatedById { get; set; }

    public virtual TUserIdentifier? ModifiedById { get; set; }

    public virtual TUserIdentifier? DeletedById { get; set; }

    [NotMapped]
    object IUserAuditableData.CreatedById
    {
      get
      {
        return CreatedById;
      }
      set
      {
        CreatedById = (TUserIdentifier?)value;
      }
    }

    [NotMapped]
    object IUserAuditableData.ModifiedById
    {
      get
      {
        return ModifiedById;
      }
      set
      {
        ModifiedById = (TUserIdentifier?)value;
      }
    }

    [NotMapped]
    object IUserAuditableData.DeletedById
    {
      get
      {
        return DeletedById;
      }
      set
      {
        DeletedById = (TUserIdentifier?)value;
      }
    }
  }

}
